home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / M_leader.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  11.4 KB  |  496 lines

  1. /*
  2. ==============================================================================
  3.  
  4. Martian Leader
  5.  
  6. ==============================================================================
  7. */
  8.  
  9. #include "g_local.h"
  10. #include "M_leader.h"
  11.  
  12.  
  13. void leader_doattack_rocket (edict_t *self);
  14. void leader_refire_rocket (edict_t *self);
  15.  
  16. static int    sound_thud;
  17. static int    sound_pain;
  18. static int    sound_idle;
  19. static int    sound_die;
  20. static int    sound_step;
  21. static int    sound_sight;
  22. static int    sound_windup;
  23. static int    sound_strike;
  24.  
  25. //
  26. // misc
  27. //
  28.  
  29. void leader_sight (edict_t *self, edict_t *other)
  30. {
  31.     gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
  32. }
  33.  
  34.  
  35. void leader_footstep (edict_t *self)
  36. {
  37.     gi.sound (self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0);
  38. }
  39.  
  40. void leader_thud (edict_t *self)
  41. {
  42.     gi.sound (self, CHAN_BODY, sound_thud, 1, ATTN_NORM, 0);
  43. }
  44.  
  45. void leader_windup (edict_t *self)
  46. {
  47.     gi.sound (self, CHAN_WEAPON, sound_windup, 1, ATTN_NORM, 0);
  48. }
  49.  
  50. void leader_idle (edict_t *self)
  51. {
  52.     gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
  53. }
  54.  
  55.  
  56. //
  57. // stand
  58. //
  59.  
  60. mframe_t leader_frames_stand []=
  61. {
  62.     ai_stand, 0, NULL,
  63.     ai_stand, 0, NULL,
  64.     ai_stand, 0, NULL,
  65.     ai_stand, 0, NULL,
  66.     ai_stand, 0, NULL,
  67.     ai_stand, 0, NULL,
  68.     ai_stand, 0, NULL,
  69.     ai_stand, 0, NULL,
  70.     ai_stand, 0, NULL,
  71.     ai_stand, 0, NULL,
  72. };
  73. mmove_t    leader_move_stand = {FRAME_idle01, FRAME_idle10, leader_frames_stand, NULL};
  74.     
  75. void leader_stand (edict_t *self)
  76. {
  77.     self->monsterinfo.currentmove = &leader_move_stand;
  78. }
  79.  
  80.  
  81. //
  82. // walk
  83. //
  84.  
  85. void leader_walk (edict_t *self);
  86.  
  87. mframe_t leader_frames_start_walk [] =
  88. {
  89.     ai_walk,  0, NULL,
  90.     ai_walk,  6, NULL,
  91.     ai_walk,  16, NULL,
  92.     ai_walk, 18, leader_footstep
  93. };
  94. mmove_t    leader_move_start_walk = {FRAME_walk01, FRAME_walk04, leader_frames_start_walk, leader_walk};
  95.  
  96. mframe_t leader_frames_walk [] =
  97. {
  98.     ai_walk, 14,    NULL,
  99.     ai_walk, 15,    NULL,
  100.     ai_walk, 13,    NULL,
  101.     ai_walk, 12,    NULL,
  102.     ai_walk, 15,    NULL,
  103.     ai_walk, 14,    NULL,
  104.     ai_walk, 14,    leader_footstep,
  105.     ai_walk, 13,    NULL,
  106.     ai_walk, 15,    NULL,
  107.     ai_walk, 17,    NULL,
  108.     ai_walk, 16,    NULL,
  109.     ai_walk, 16,    leader_footstep
  110. };
  111. mmove_t    leader_move_walk = {FRAME_walk01, FRAME_walk12, leader_frames_walk, NULL};
  112.  
  113. mframe_t leader_frames_stop_walk [] =
  114. {
  115.     ai_walk,  13, NULL,
  116.     ai_walk,  13, NULL,
  117.     ai_walk,  12, NULL,
  118.     ai_walk,  12, NULL,
  119.     ai_walk,  14, leader_footstep
  120. };
  121. mmove_t    leader_move_stop_walk = {FRAME_walk08, FRAME_walk12, leader_frames_stop_walk, leader_stand};
  122.  
  123. void leader_walk (edict_t *self)
  124. {
  125.         self->monsterinfo.currentmove = &leader_move_walk;
  126. }
  127.  
  128.  
  129. //
  130. // run
  131. //
  132.  
  133. void leader_run (edict_t *self);
  134.  
  135. mframe_t leader_frames_start_run [] =
  136. {
  137.     ai_run,  0, NULL,
  138.     ai_run,  16, NULL,
  139.     ai_run,  16, NULL,
  140.     ai_run, 21, leader_footstep
  141. };
  142. mmove_t    leader_move_start_run = {FRAME_walk01, FRAME_walk04, leader_frames_start_run, leader_run};
  143.  
  144. mframe_t leader_frames_run [] =
  145. {
  146.     ai_run, 14,    NULL,
  147.     ai_run, 15,    NULL,
  148.     ai_run, 13,    NULL,
  149.     ai_run, 12,    NULL,
  150.     ai_run, 15,    NULL,
  151.     ai_run, 14,    NULL,
  152.     ai_run, 14,    leader_footstep,
  153.     ai_run, 13,    NULL,
  154.     ai_run, 15,    NULL,
  155.     ai_run, 17,    NULL,
  156.     ai_run, 16,    NULL,
  157.     ai_run, 16,    leader_footstep
  158. };
  159. mmove_t    leader_move_run = {FRAME_walk01, FRAME_walk12, leader_frames_run, NULL};
  160.  
  161. mframe_t leader_frames_stop_run [] =
  162. {
  163.     ai_run,  13, NULL,
  164.     ai_run,  13, NULL,
  165.     ai_run,  12, NULL,
  166.     ai_run,  12, NULL,
  167.     ai_run,  14, leader_footstep
  168. };
  169. mmove_t    leader_move_stop_run = {FRAME_walk08, FRAME_walk12, leader_frames_stop_run, leader_walk};
  170.  
  171. void leader_run (edict_t *self)
  172. {
  173.     if (self->enemy && self->enemy->client)
  174.         self->monsterinfo.aiflags |= AI_BRUTAL;
  175.     else
  176.         self->monsterinfo.aiflags &= ~AI_BRUTAL;
  177.  
  178.     if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  179.     {
  180.         self->monsterinfo.currentmove = &leader_move_stand;
  181.         return;
  182.     }
  183.  
  184.     if (self->monsterinfo.currentmove == &leader_move_walk ||
  185.         self->monsterinfo.currentmove == &leader_move_start_run)
  186.     {
  187.         self->monsterinfo.currentmove = &leader_move_run;
  188.     }
  189.     else
  190.     {
  191.         self->monsterinfo.currentmove = &leader_move_start_run;
  192.     }
  193. }
  194.  
  195. //
  196. // pain
  197. //
  198.  
  199. mframe_t leader_frames_pain1 [] =
  200. {
  201.     ai_move, 0, NULL,
  202.     ai_move, 0, NULL,
  203.     ai_move, 0, NULL,
  204.     ai_move, 0, NULL,
  205.     ai_move, 0, NULL,
  206.     ai_move, 0, NULL,
  207.     ai_move, 0, NULL,
  208.     ai_move, 0, NULL,
  209.     ai_move, 0, NULL,
  210.     ai_move, 0, NULL,
  211.     ai_move, 0, NULL,
  212.     ai_move, 0, NULL
  213. };
  214. mmove_t leader_move_pain1 = {FRAME_pain01, FRAME_pain12, leader_frames_pain1, leader_run};
  215.  
  216. mframe_t leader_frames_pain2 [] =
  217. {
  218.     ai_move, 0, NULL,
  219.     ai_move, 0, NULL,
  220.     ai_move, 0, NULL,
  221.     ai_move, 0, NULL,
  222.     ai_move, 0, NULL,
  223.     ai_move, 0, NULL,
  224.     ai_move, 0, NULL,
  225.     ai_move, 0, NULL,
  226.     ai_move, 0, NULL,
  227.     ai_move, 0, NULL,
  228.     ai_move, 0, NULL,
  229.     ai_move, 0, NULL
  230. };
  231. mmove_t leader_move_pain2 = {FRAME_pain01, FRAME_pain12, leader_frames_pain2, leader_run};
  232.  
  233. void leader_pain (edict_t *self, edict_t *other, float kick, int damage)
  234. {
  235.     if (self->health < (self->max_health / 2))
  236.             self->s.skinnum |= 1;
  237.  
  238.     if (damage <= 10)
  239.         return;
  240.  
  241.     if (level.time < self->pain_debounce_time)
  242.             return;
  243.  
  244.     if (damage <= 30)
  245.         if (random() > 0.2)
  246.             return;
  247.     
  248.     // If hard or nightmare, don't go into pain while attacking
  249.  
  250.     self->pain_debounce_time = level.time + 3;
  251.     gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
  252.  
  253.     if (damage <= 30)
  254.         
  255.         self->monsterinfo.currentmove = &leader_move_pain1;
  256.     else
  257.         self->monsterinfo.currentmove = &leader_move_pain2;
  258. };
  259.  
  260.  
  261. //
  262. // attacks
  263. //
  264.  
  265. void leaderStrike (edict_t *self)
  266. {
  267.     gi.sound (self, CHAN_WEAPON, sound_strike, 1, ATTN_NORM, 0);
  268. }    
  269.  
  270. void leaderRocket (edict_t *self)
  271. {
  272.     vec3_t    forward, right;
  273.     vec3_t    start;
  274.     vec3_t    dir;
  275.     vec3_t    vec;
  276.     vec3_t  temp;
  277.     int        flash_number;
  278.  
  279.     if (self->s.frame == FRAME_attack04)
  280.         flash_number = MZ2_TANK_ROCKET_1;
  281.     else if (self->s.frame == FRAME_attack04)
  282.         flash_number = MZ2_TANK_ROCKET_2;
  283.     else // (self->s.frame == FRAME_attak330)
  284.         flash_number = MZ2_TANK_ROCKET_3;
  285.  
  286.     AngleVectors (self->s.angles, forward, right, NULL);
  287.     right[0] = right[0] * -3.0;
  288.     right[1] = right[1] * -3.0;
  289.     VectorCopy (self->s.origin, temp);
  290.     temp[2] = temp[2] - 32;
  291.     G_ProjectSource (temp, monster_flash_offset[flash_number], forward, right, start);
  292.  
  293.     VectorCopy (self->enemy->s.origin, vec);
  294.     vec[2] += self->enemy->viewheight;
  295.     VectorSubtract (vec, start, dir);
  296.     VectorNormalize (dir);
  297.  
  298.     monster_fire_stinger (self, start, dir, 50, 550, flash_number);
  299. }    
  300.  
  301.  
  302. mframe_t leader_frames_attack_fire_rocket [] =
  303. {
  304.     ai_charge, -3, NULL,            // Loop Start    22 
  305.     ai_charge, 0,  NULL,
  306.     ai_charge, 0,  NULL,
  307.     ai_charge, 0,  NULL,
  308.     ai_charge, 0,  NULL,
  309.     ai_charge, 0,  NULL,
  310.     ai_charge, 0,  leaderRocket,
  311.     ai_charge, 0,  NULL,
  312.     ai_charge, 0,  NULL,
  313.     ai_charge, 0,  NULL,
  314.     ai_charge, 0,  NULL,
  315.     ai_charge, -1, NULL        // 30    Loop End
  316. };
  317. mmove_t leader_move_attack_fire_rocket = {FRAME_attack01, FRAME_attack12, leader_frames_attack_fire_rocket, leader_refire_rocket};
  318.  
  319. mframe_t leader_frames_attack_post_rocket [] =
  320. {    
  321.     ai_charge, -9, NULL,
  322.     ai_charge, -8, NULL,
  323.     ai_charge, -7, NULL,
  324.     ai_charge, -1, NULL,
  325.     ai_charge, -1, leader_footstep,
  326.     ai_charge, 0,  NULL,
  327.     ai_charge, 0,  NULL,
  328.     ai_charge, 0,  NULL
  329. };
  330. mmove_t leader_move_attack_post_rocket = {FRAME_walk01, FRAME_walk08, leader_frames_attack_post_rocket, leader_run};
  331.  
  332. void leader_refire_rocket (edict_t *self)
  333. {
  334.     // Only on hard or nightmare
  335.     if ( skill->value >= 2 )
  336.         if (self->enemy->health > 0)
  337.             if (visible(self, self->enemy) )
  338.                 if (random() <= 0.4)
  339.                 {
  340.                     self->monsterinfo.currentmove = &leader_move_attack_fire_rocket;
  341.                     return;
  342.                 }
  343.     self->monsterinfo.currentmove = &leader_move_attack_post_rocket;
  344. }
  345.  
  346. void leader_doattack_rocket (edict_t *self)
  347. {
  348.     self->monsterinfo.currentmove = &leader_move_attack_fire_rocket;
  349. }
  350.  
  351. void leader_attack(edict_t *self)
  352. {
  353.     vec3_t    vec;
  354.     float    range;
  355.     float    r;
  356.  
  357.  
  358.     VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
  359.     range = VectorLength (vec);
  360.  
  361.     r = random();
  362.  
  363.             self->monsterinfo.currentmove = &leader_move_attack_fire_rocket;
  364.             self->pain_debounce_time = level.time + 5.0;    // no pain for a while
  365. }
  366.  
  367.  
  368. //
  369. // death
  370. //
  371.  
  372. void leader_dead (edict_t *self)
  373. {
  374.  
  375.     BecomeExplosion1(self);
  376.     VectorSet (self->mins, -16, -16, -56);
  377.     VectorSet (self->maxs, 16, 16, -8);
  378.     self->movetype = MOVETYPE_TOSS;
  379.     self->svflags |= SVF_DEADMONSTER;
  380.     self->nextthink = 0;
  381.     gi.linkentity (self);
  382. }
  383.  
  384. mframe_t leader_frames_death1 [] =
  385. {
  386.     ai_move, 0,  NULL,
  387.     ai_move, 0,  NULL,
  388.     ai_move, 0,  NULL,
  389.     ai_move, 0,  NULL,
  390.     ai_move, 0,  NULL,
  391.     ai_move, 0,  NULL,
  392.     ai_move, 0,  NULL,
  393.     ai_move, 0,  NULL,
  394.     ai_move, 0,  NULL,
  395.     ai_move, 0,  NULL,
  396.     ai_move, 0,  NULL,
  397.     ai_move, 0,  NULL
  398. };
  399. mmove_t    leader_move_death = {FRAME_death01, FRAME_death12, leader_frames_death1, leader_dead};
  400.  
  401. void leader_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  402. {
  403.     int        n;
  404.  
  405. // check for gib
  406.     if (self->health <= self->gib_health)
  407.     {
  408.         gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
  409.         for (n= 0; n < 1 /*4*/; n++)
  410.             ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
  411.         for (n= 0; n < 4; n++)
  412.             ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC);
  413.         ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC);
  414.         ThrowHead (self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC);
  415.         self->deadflag = DEAD_DEAD;
  416.         return;
  417.     }
  418.  
  419.     if (self->deadflag == DEAD_DEAD)
  420.         return;
  421.  
  422. // regular death
  423.  
  424.     self->deadflag = DEAD_DEAD;
  425.     self->takedamage = DAMAGE_YES;
  426.  
  427.     self->monsterinfo.currentmove = &leader_move_death;
  428.     
  429. }
  430.  
  431.  
  432. //
  433. // monster_leader
  434. //
  435.  
  436. /*QUAKED monster_leader (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight
  437. */
  438. /*QUAKED monster_leader_commander (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight
  439. */
  440. void SP_monster_leader (edict_t *self)
  441. {
  442.     if (deathmatch->value)
  443.     {
  444.         G_FreeEdict (self);
  445.         return;
  446.     }
  447.  
  448.     self->s.modelindex = gi.modelindex ("models/monsters/alien3/tris.md2");
  449.     VectorSet (self->mins, -64, -64, -56);
  450.     VectorSet (self->maxs, 64, 64, 32);
  451.     self->movetype = MOVETYPE_STEP;
  452.     self->solid = SOLID_BBOX;
  453.  
  454.     sound_pain = gi.soundindex ("robot9/move1.wav");
  455.     sound_thud = gi.soundindex ("tank/tnkdeth2.wav");
  456.     sound_idle = gi.soundindex ("robot9/move3.wav");
  457.     sound_die = gi.soundindex ("tank/death.wav");
  458.     sound_step = gi.soundindex ("robot9/servo.wav");
  459.     sound_windup = gi.soundindex ("robot9/servo.wav");
  460.     sound_strike = gi.soundindex ("robot9/move2.wav");
  461.     sound_sight = gi.soundindex ("robot9/move3.wav");
  462.  
  463.     gi.soundindex ("tank/tnkatck1.wav");
  464.     gi.soundindex ("tank/tnkatk2a.wav");
  465.     gi.soundindex ("tank/tnkatk2b.wav");
  466.     gi.soundindex ("tank/tnkatk2c.wav");
  467.     gi.soundindex ("tank/tnkatk2d.wav");
  468.     gi.soundindex ("tank/tnkatk2e.wav");
  469.     gi.soundindex ("tank/tnkatck3.wav");
  470.  
  471.         self->health = 750;
  472.         self->gib_health = -200;
  473.     
  474.     self->mass = 500;
  475.  
  476.     self->pain = leader_pain;
  477.     self->die = leader_die;
  478.     self->monsterinfo.stand = leader_stand;
  479.     self->monsterinfo.walk = leader_walk;
  480.     self->monsterinfo.run = leader_run;
  481.     self->monsterinfo.dodge = NULL;
  482.     self->monsterinfo.attack = leader_attack;
  483.     self->monsterinfo.melee = NULL;
  484.     self->monsterinfo.sight = leader_sight;
  485.     self->monsterinfo.idle = leader_idle;
  486.  
  487.     gi.linkentity (self);
  488.     
  489.     self->monsterinfo.currentmove = &leader_move_stand;
  490.     self->monsterinfo.scale = MODEL_SCALE;
  491.  
  492.     walkmonster_start(self);
  493.  
  494.         
  495. }
  496.